package com.pat.java.base.socket;

import java.applet.Applet;
import java.awt.Button;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;

public class TalkSelf extends Applet implements Runnable, ActionListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static String SERVER_NAME ;	// "192.100.100.42";
	private static int SRTPPort = 1734;
	private static int MAXBUFFER = 8192;
	final int bufSize = 16384;
	private static boolean PlayButton = false;	//是否播放按钮
	private static boolean keepRunning = true;	//控制循环
	private boolean bRun = false;	//控制播放
	private Thread TalkThread;
	private static PlaybackAudio PlayAudio;		//播放音频实例
	private static CaptureAudio CapAudio;		//采集音频实例
	Button PlayBtn;			//通话按钮
	Button CaptureBtn;		//停止按钮
	
	//初始化界面
	public void init() {
		PlayBtn = new Button("通话");
		PlayBtn.addActionListener(this);
		add(PlayBtn);
		CaptureBtn = new Button("停止");
		CaptureBtn.addActionListener(this);
		add(CaptureBtn);
	}
	
	//启动线程
	public void start() {
		if (TalkThread == null) {
			TalkThread = new Thread(this);
			TalkThread.start();
		}
	}

	//响应事件
	public void actionPerformed(ActionEvent evt) {
		String btnCaption = evt.getActionCommand();
		if (btnCaption.equals("通话")) {
			PlayButton = true;
		}
		if (btnCaption.equals("停止")) {
			PlayButton = false;
			bRun = false;
		}
	}

	//实现run函数
	public void run() {
		while (keepRunning) {
			if (PlayButton && !bRun){
				try {
					bRun = true;
					CapAudio = new CaptureAudio(SERVER_NAME, SRTPPort);
					CapAudio.start();
					PlayAudio = new PlaybackAudio(SRTPPort);
					PlayAudio.start();
				} catch (Exception e) {
					System.out.println(e.getMessage());
				}
			}
		}
	}

	//音频播放类
	class PlaybackAudio extends Thread implements Runnable {
		SourceDataLine line;
		Thread thread;
		DatagramSocket s;	//数据包Socket
		DatagramPacket p;	//数据报包
		int RTPPort;
		
		//构造函数：取得接受端口
		PlaybackAudio(int RTPPort) {
			this.RTPPort = RTPPort;
		}

		public void start() {
			thread = new Thread(this);
			thread.setName("PlaybackAudio");
			thread.start();
		}

		public void run() {
			AudioFormat format = new
			
			//设置音频格式
			AudioFormat(8000, 16, 2, true, true);
			
			//设置数据线
			DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
			try {
				//获得源数据线信息
				line = (SourceDataLine) AudioSystem.getLine(info);
				
				//打开源数据线
				line.open(format, bufSize);
			} catch (LineUnavailableException ex) {
				return;
			}

			byte[] data = new byte[MAXBUFFER];
			int numBytesRead = 0;
			
			//启动源数据线
			line.start();
			try {
				s = new DatagramSocket(RTPPort);
			} catch (IOException e) {
				return;
			}
			while (thread != null) {
				try {
					p = new DatagramPacket(data, data.length);
					
					//接收包
					s.receive(p);
					numBytesRead = p.getLength();
					
					//写入源数据线
					line.write(p.getData(), 0, numBytesRead);
				} catch (IOException e) {
					break;
				}
			}
			
			//关闭数据报Socket
			s.close();
			if (thread != null) {
				line.drain();
			}
			line.stop();
			line.close();
			line = null;
		}
	}

	//音频采集类
	class CaptureAudio extends Thread implements Runnable {

		TargetDataLine line;
		Thread thread;
		DatagramSocket s;
		DatagramPacket p;
		String SERVER_NAME;
		int RTPPort;

		//构造函数：取得远程服务器名和端口，用于发送数据
		CaptureAudio(String SERVER_NAME, int RTPPort) {
			this.SERVER_NAME = SERVER_NAME;
			this.RTPPort = RTPPort;
		}

		public void start() {

			thread = new Thread(this);
			thread.setName("CaptureAudio");
			thread.start();
		}

		public void run() {
			AudioFormat format = new AudioFormat(8000, 16, 2, true, true);
			// AudioFormat(float sampleRate,int sampleSizeInBits, int channels,
			// boolean signed, boolean bigEndian)
			DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);

			try {
				//设置目标数据线信息
				line = (TargetDataLine) AudioSystem.getLine(info);
				
				//打开目标数据线
				line.open(format, line.getBufferSize());
			} catch (Exception ex) {
				return;
			}
			byte[] data = new byte[MAXBUFFER];
			int numBytesRead = 0;
			
			//启动目标数据线
			line.start();
			try{
				//构造数据报Socket
				s = new DatagramSocket();
			} catch (Exception ex) {
				return;
			}
			while (thread != null) {
				try {
					//读取采集数据
					numBytesRead = line.read(data, 0, MAXBUFFER);
					
					//发送数据
					p = new DatagramPacket(data, numBytesRead,
							InetAddress.getByName(SERVER_NAME), RTPPort);
					s.send(p);
				} catch (Exception ex) {
					break;
				}
			}
			s.close();
			line.stop();
			line.close();
			line = null;
		}
	}

	//主函数
	@SuppressWarnings("deprecation")
	public static void main(String args[]) {
		SERVER_NAME = new String("127.0.0.1");
		TalkSelf t = new TalkSelf();
		Frame f = new Frame();
		f.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent evt) {
				System.exit(0);
			}
		});

		t.init();
		f.setSize(300, 300);
		f.add("Center", t);
		f.show();
		t.start();
	}
}
